home *** CD-ROM | disk | FTP | other *** search
/ Die Speccy' 97 / Die Speccy' 97.iso / amiga_system / the_aminet / comm / tcp / mufs_telnetd.lha / telnetd.c < prev    next >
C/C++ Source or Header  |  1992-09-02  |  70KB  |  1,701 lines

  1. /*
  2.  *      $Filename: telnetd.c $
  3.  *      $Revision: 2.0 $
  4.  *      $Date: 1995/04/13 19:53:48 $
  5.  *
  6.  *      Copyright (C) 1993,94 by Steve Holland <sdh4@cornell.edu>
  7.  *      Copyright (C) 1995 by Peter Simons <simons@peti.rhein.de>
  8.  *
  9.  *      This program is free software; you can redistribute it and/or
  10.  *      modify it under the terms of the GNU General Public License as
  11.  *      published by the Free Software Foundation; either version 2 of
  12.  *      the License, or (at your option) any later version.
  13.  *
  14.  *      This program is distributed in the hope that it will be useful,
  15.  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  17.  *      General Public License for more details.
  18.  *
  19.  *      You should have received a copy of the GNU General Public License
  20.  *      along with this program; if not, write to the Free Software
  21.  *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  22.  *
  23.  *      $Id: telnetd.c 2.0  1995/04/13 19:53:48 simons Exp $
  24.  *
  25.  *      *********************************************************
  26.  *    *    WARNING WARNING WARNING WARNING WARNING !!!    *
  27.  *     *********************************************************
  28.  *
  29.  *     Telnetd source code has been modified by Andrea Rafreider
  30.  *      (andsk@amiga.dei.unipd.it) in order to make it MultiUser compatible.
  31.  *    
  32.  *    This modify of the original source code from Steve Holland and
  33.  *    Peter Simons was made on date 1995/05/04.
  34.  *    
  35.  *    Original version of telnetd2.0 with source can be found in this
  36.  *    same archive.
  37.  *
  38.  *    Watch the file Multiuser.txt to see what is MultiUser, and what can
  39.  *    be done with it.
  40.  *
  41.  *      With *this* modified telnetd, passwd checking is done via
  42.  *    multiuser.library instead of usergroup.library from AmiTCP.
  43.  *
  44.  *      The main advantage is that giving a shell to a remote user is
  45.  *    no longer *totally* insecure because of multiuser protection 
  46.  *    mechanisms.
  47.  *
  48.  *     Obviously for better security the system manager should protect
  49.  *    all the "hot" commands with root permissions only.
  50.  *    
  51.  *    It's no longer possible to log in without password if the passwd field
  52.  *    in the multiuser passwd file is "*".
  53.  *    Some annoying syslog messages have also been removed.
  54.  *
  55.  *    The password checking is done via multiuser.library so that multiuser
  56.  *     passwd file can be protected from indiscreet eyes with the following
  57.  *     protection bits:  root ----rwed group ---- other ----    
  58.  *
  59.  *    I really don't see why AmiTCP group have complicated things not
  60.  *    using ACrypt() criptographic function from Commodore. To set up
  61.  *    a multiuser environement with AmiTCP one should have two passwd 
  62.  *    files !! One for AmiTCP, and another one for MultiUser!!
  63.  *    This is ridiculous.
  64.  *
  65.  *    In our amiga system at University we don't use AmiTCP passwd file
  66.  *    at all ! Clients don't need it and as daemons we use JoranFTPd and
  67.  *     now this modified telnetd.
  68.  *
  69.  *    I'm considering the idea of creating a fake usergroup.library from
  70.  *    the free usergroup.library source code that makes passwd checks via
  71.  *    ACrypt() function from Commodore, so we could end up with this silly
  72.  *     problems.
  73.  *
  74.  *     That's all folks!!
  75.  *                    Andrea Rafreider.
  76.  *
  77.  *    Please see also the GNU General Public Licence included in this archive.
  78.  *    to agree with terms and conditions of the distribution of this package. 
  79.  */
  80.  
  81. /************************************* includes ***********/
  82. #include <exec/types.h>
  83. #include <exec/memory.h>
  84. #include <sys/types.h>
  85. #include <sys/socket.h>
  86. #include <sys/param.h>
  87. #include <dos/dos.h>
  88. #include <dos/dosextens.h>
  89. #include <dos/dostags.h>
  90. #include <proto/dos.h>
  91. #include <proto/exec.h>
  92. #include <proto/utility.h>
  93. #include <proto/usergroup.h>
  94. #include <errno.h>
  95. #include <sys/ioctl.h>
  96. #include <exec/errors.h>
  97. #include <devices/serial.h>
  98. #include <string.h>
  99. #include <stdlib.h>
  100. #include <stdio.h>
  101. #include <inetd.h>
  102. #include <syslog.h>
  103. #include <amitcp/socketbasetags.h>
  104.  
  105. /* Next 3 includes are added by Mr. Andsk */
  106.  
  107. #include <utility/tagitem.h>
  108. #include <libraries/multiuser.h>
  109. #include <proto/multiuser.h>
  110.  
  111. #include <fakesr.h>
  112.  
  113. #include "telnetd_rev.h"
  114.  
  115. /************************************* structures *********/
  116.  
  117. struct InstData {
  118.         struct Library *DOSB;
  119.         struct Library *SocketB;
  120.         struct Library *UtilityB;
  121.         struct Library *UserGroupB;
  122.         int Socket;
  123.         signed short RecvBuf[1024];
  124.         int RecvBufPos;
  125.         int RecvBufFlags;
  126. };
  127.  
  128. struct PasswdInfo {
  129.         char Login[50];
  130.         char Passwd[50];
  131.         char RealName[150];
  132.         char WorkDir[256];
  133.         char Command[512];
  134. };
  135.  
  136. /************************************* defines ************/
  137. #define DOSBase Inst->DOSB
  138. #define UtilityBase Inst->UtilityB
  139. #define SocketBase Inst->SocketB
  140. #define UserGroupBase Inst->UserGroupB
  141. #define Socket Inst->Socket
  142.  
  143. /* telnet symbols */
  144. #define IAC 255
  145. #define WILL 251
  146. #define WONT 252
  147. #define DO 253
  148. #define DONT 254
  149. #define ECHO 1
  150. #define LINEMODE 34
  151. #define SE 240
  152. #define SB 250
  153. #define MODE 1
  154. #define EDIT 1
  155.  
  156. #define RBF_SUBNEGOTIATE (1<<0)         /* Defines for RecvBufFlags */
  157.  
  158. /************************************* global variables ***/
  159. static const char __DOSVer[] = VERSTAG " written by Peter Simons <simons@peti.rhein.de>";
  160. #ifndef USE_INETD
  161. struct Library *SysBase;
  162. #endif
  163. char *Signature="FAKEMSG--EXPUNGE";
  164.  
  165. /************************************* prototypes *********/
  166. void SockPuts(struct InstData *Inst,int Sock,char *Buf);
  167. void SockGets(struct InstData *Inst,int Sock,char *Buf,int BufSize);
  168. unsigned long GetInt(char *String,char **NewPtr);
  169. struct PasswdInfo *LookupPasswd(struct InstData *Inst,char *Login);
  170. int __asm SubSubProc(register __a0 char *ArgString,register __d0 long Length);
  171. struct DosPacket *PktFromMsg(struct Message *Msg);
  172. void MakeLongStr(char *StrBuf,unsigned long Num);
  173. void SockWrite(struct InstData *Inst,int Sock,char *Buf,int Len,int RawFlag);
  174. int RecvChar(struct InstData *Inst,int Sock,unsigned char *Loc,int RawMode);
  175. struct Process *MyCreateNewProcTags(struct InstData *,ULONG,...);
  176. void *MyAllocDosObjectTags(struct InstData *,ULONG,ULONG,...);
  177. void PktFPuts(struct InstData *Inst,BPTR File,char *String);
  178. void SockRawWrite(struct InstData *Inst,int Sock,char *Buf,int Len);
  179. void MySystemTags(struct Library *DSBse,char *Cmd,ULONG Tag0,...);
  180. void mystrcat(char *Dest,char *Cat);
  181. void MyFPrintf(struct InstData *Inst,BPTR File,char *Fmt,...);
  182.  
  183. ULONG FakeBeginIO(void *IORequest);
  184. ULONG FakeAbortIO(void *IORequest);
  185. ULONG FakeOpen(void *IORequest);
  186. ULONG FakeClose(void *IORequest);
  187. void mymovmem(char *From,char *To,int Len);
  188.  
  189. #define NewList(list) {(list)->lh_Head=(struct Node *)&(list)->lh_Tail;(list)->lh_Tail=NULL;(list)->lh_TailPred=(struct Node *)&(list)->lh_Head;}
  190.  
  191. #ifdef DEBUG
  192.   BPTR DebugFile;
  193. #endif
  194.  
  195. #ifdef USE_INETD
  196. int main(void)
  197. #else
  198. int __asm main(register __a0 char *ArgStr,register __d0 long Length)
  199. /* ArgString will look like: "[SocketID] [SigNum] [ParentTaskID]" */
  200. #endif
  201. {
  202.         int Cnt;
  203.     char A_Buf[20];  /* temporary buffer for ACrypt() */
  204.         unsigned long SockID,SigID,TaskID;
  205.         char Buf[1000],LoginBuf[50], MyPrgName[64];
  206.         BPTR BannerFile=NULL;
  207.     struct muBase *muBase = NULL;       /* added by andsk */
  208.     struct TagItem tags[3];            /* added by andsk */
  209.     struct muUserInfo *muInfo = NULL;     /* added by andsk */
  210.         struct InstData *Inst=NULL;
  211.         struct PasswdInfo *Info=NULL;
  212.         struct FileHandle *FH;
  213.         struct Message *Msg,*GotMsg;
  214.         unsigned char NoEcho[7];
  215.         unsigned char Echo[14];
  216.         char *ArgString;
  217.         int OpenCount=0;
  218.         int AmntRead;
  219.         int HangupFlag=FALSE;
  220.  
  221.         ULONG SigMask;
  222.         long yes=TRUE;
  223.         fd_set RdSet;
  224.         fd_set WrSet;
  225.         struct List ReadWaitList;
  226.         struct DosPacket *Pkt;
  227.         int Err;
  228.         unsigned char Chr,NumBuf[30];
  229.         int RawMode=FALSE;
  230.         int NextChar=-1;
  231.         struct MsgPort *TimePort;
  232.         struct timerequest *TimeReq;
  233.         struct DaemonMessage *InetdStartup;
  234.         struct Process *Self;
  235.  
  236.  
  237. #ifndef USE_INETD
  238.         SysBase=*((struct Library **)0x00000004);
  239.         ArgString=ArgStr;
  240. #endif
  241.         Echo[0]=NoEcho[0]=IAC;
  242.         Echo[1]=WONT;
  243.         Echo[2]=ECHO;
  244.         Echo[3]=IAC;
  245.         Echo[4]=DO;
  246.         Echo[5]=LINEMODE;
  247.         Echo[6]=IAC;
  248.         Echo[7]=SB;
  249.         Echo[8]=LINEMODE;
  250.         Echo[9]=MODE;
  251.         Echo[10]=EDIT;
  252.         Echo[11]=IAC;
  253.         Echo[12]=SE;
  254.         NoEcho[1]=WILL;
  255.         NoEcho[2]=ECHO;
  256.         NoEcho[3]=IAC;
  257.         NoEcho[4]=DONT;
  258.         NoEcho[5]=LINEMODE;
  259.         Echo[13]=NoEcho[6]='\0';
  260.  
  261. #ifndef USE_INETD
  262.         for (Cnt=0;Cnt < Length;Cnt++) {
  263.                 if (ArgStr[Cnt]!=' ' && (ArgStr[Cnt] < '0' || ArgStr[Cnt] > '9'))
  264.                         return ERROR_FILE_NOT_OBJECT;
  265.         }
  266. #endif
  267.         Inst=AllocMem(sizeof(struct InstData),MEMF_CLEAR);
  268.         if (!Inst) return 0;
  269.     
  270.     muBase=OpenLibrary("multiuser.library",39); /* added by andsk */
  271.         DOSBase=OpenLibrary("dos.library",36);
  272.         UtilityBase=OpenLibrary("utility.library",36);
  273.         SocketBase=OpenLibrary("bsdsocket.library",2);
  274.         UserGroupBase=OldOpenLibrary(USERGROUPNAME);
  275.  
  276.         TimePort=CreateMsgPort();
  277.         NewList(&ReadWaitList);
  278.  
  279.         if (!DOSBase || !UtilityBase || !SocketBase || !UserGroupBase || !TimePort || !muBase) return 0; /* added check for multiuser.library */
  280.  
  281.         SocketBaseTags(SBTM_SETVAL(SBTC_LOGTAGPTR), "telnetd",
  282.                  SBTM_SETVAL(SBTC_LOGSTAT), 0,
  283.                  SBTM_SETVAL(SBTC_LOGFACILITY), LOG_AUTH,
  284.                  TAG_END);
  285.  
  286. #ifdef DEBUG
  287.         DebugFile=Open("con:0/0/500/100/telnetd DEBUG/WAIT/CLOSE",MODE_OLDFILE);
  288.         FPuts(DebugFile,"telnetd starting\n");
  289. #  ifndef USE_INETD
  290.         FPuts(DebugFile,"ArgString=");
  291.         FPuts(DebugFile,ArgString);
  292.         FPuts(DebugFile,"\n");
  293. #  endif
  294.  
  295. #endif
  296.  
  297. #ifdef USE_INETD
  298.         Self=(struct Process *) FindTask(NULL);
  299.         InetdStartup=(struct DaemonMessage *)Self->pr_ExitData;
  300.         if (!InetdStartup) goto quit;
  301.         Socket=ObtainSocket(InetdStartup->dm_Id,InetdStartup->dm_Family,InetdStartup->dm_Type,0);
  302.         if (Socket < 0) goto quit;
  303. #else
  304.         /* Get arguments */
  305.         SockID=GetInt(ArgString,&ArgString);
  306.         ArgString++; /* Skip over space */
  307.         SigID=GetInt(ArgString,&ArgString);
  308.         ArgString++; /* Skip over space */
  309.         TaskID=GetInt(ArgString,&ArgString);
  310.         /* After this call, the parameter string is no longer valid */
  311.         Signal((struct Task *)TaskID,1<<SigID);
  312. #ifdef DEBUG
  313.         FPuts(DebugFile,"Signaled parent\n");
  314. #endif
  315.  
  316.         /* We're on our own now */
  317.         Socket=ObtainSocket(SockID,AF_INET,SOCK_STREAM,0);
  318.         if (Socket < 0) goto quit;
  319.  
  320. #endif
  321.  
  322. #ifdef DEBUG
  323.         FPuts(DebugFile,"Got Socket\n");
  324. #endif
  325.  
  326.         /* First, display banner, ask for password, etc */
  327.         if (BannerFile=Open("AmiTCP:db/telnetd_banner",MODE_OLDFILE)) {
  328.                 int len = 1;
  329.  
  330.                 while(TRUE) {
  331.                         len = Read(BannerFile, Buf, sizeof(Buf));
  332.                         if (!len || len == -1)
  333.                                 break;
  334.                         SockWrite(Inst,Socket,Buf,len,FALSE);
  335.                 }
  336.                 Close(BannerFile);
  337.         }
  338.  
  339. #ifdef DEBUG
  340.         FPuts(DebugFile,"Wrote banner to socket\n");
  341. #endif
  342.         /* Get login name */
  343.         SockPuts(Inst,Socket,"Login: ");
  344.         SockPuts(Inst,Socket,Echo);
  345.         SockGets(Inst,Socket,LoginBuf,sizeof(LoginBuf));
  346.         while (strlen(LoginBuf) && (LoginBuf[strlen(LoginBuf)-1]=='\n' || LoginBuf[strlen(LoginBuf)-1]=='\r'))
  347.                 LoginBuf[strlen(LoginBuf)-1]='\0';
  348. #ifdef DEBUG
  349.         FPuts(DebugFile,"Got Login: ");
  350.         FPuts(DebugFile,LoginBuf);
  351.         FPuts(DebugFile,"\n");
  352. #endif
  353.  
  354. /*      Info = LookupPasswd(Inst, LoginBuf);            not needed anymore    */
  355. /*    We get now info for connecting user via multiuser.library            */
  356.  
  357.     if (muInfo = muAllocUserInfo()) {
  358.         strcpy(muInfo->UserID,LoginBuf);
  359.         if (!muGetUserInfo(muInfo,muKeyType_UserID)) {
  360.             muFreeUserInfo(muInfo);
  361.             muInfo = NULL;
  362.         }
  363.         else if (Info=AllocMem(sizeof(struct PasswdInfo),MEMF_PUBLIC)) {
  364.             strcpy(Info->Login,muInfo->UserID);
  365.             strcpy(Info->Passwd,"faked_passwd!"); /* not returned by muGetUserInfo, not needed anyway! */
  366.             strcpy(Info->RealName,muInfo->UserName);
  367.             strcpy(Info->WorkDir,muInfo->HomeDir);
  368.             strcpy(Info->Command,muInfo->Shell);
  369.         }
  370.         else
  371.             syslog(LOG_CRIT, "Couldn't allocate my info structure!");
  372.     }
  373.         else
  374.                 syslog(LOG_CRIT, "Couldn't allocate memory muInfo structure!");
  375.         
  376.         /*
  377.          * We don't get asked for password if user doesn't exist
  378.          * or the shell is equal "nologin", we are just pulled out.
  379.          * 
  380.      *             WARNING !!
  381.      *
  382.      * Code is changed a little bit ..
  383.      * No more you can get logged in if your passwd is "*" for multiuser
  384.      * compatibility.
  385.          */
  386.         if (Info && strcmp("nologin", Info->Command)) {
  387.                 strcpy(Buf, "Password: ");
  388.                 strcpy(Buf+strlen(Buf), NoEcho);
  389.                 SockPuts(Inst, Socket, Buf);
  390.                 SockGets(Inst, Socket, Buf,sizeof(Buf));
  391.                 while (strlen(Buf) && (Buf[strlen(Buf)-1]=='\n' || Buf[strlen(Buf)-1]=='\r'))
  392.                         Buf[strlen(Buf)-1]='\0';
  393.                 SockPuts(Inst,Socket,Echo);
  394. #ifdef DEBUG
  395.                 FPuts(DebugFile,"Got Password: ");
  396.                 FPuts(DebugFile,Buf);
  397.                 FPuts(DebugFile,"\n");
  398. #endif
  399.  
  400.          SockPuts(Inst,Socket,"\n");
  401.  
  402.         /* We must be sure that current user is nobody */
  403.  
  404.         tags[0].ti_Tag = muT_Quiet;
  405.         tags[0].ti_Data = TRUE;
  406.         tags[1].ti_Tag = TAG_DONE;
  407.         (void) muLogoutA(tags);
  408.  
  409.         /*        MultiUser login               */
  410.  
  411.         tags[0].ti_Tag = muT_UserID;
  412.         tags[0].ti_Data = Info->Login;    
  413.         tags[1].ti_Tag = muT_Password;
  414.         tags[1].ti_Data = Buf;
  415.         tags[2].ti_Tag = TAG_DONE;
  416.         if (!muLoginA(tags)) {
  417.             SockPuts(Inst,Socket,"Login failed!\n");
  418.             CloseSocket(Socket);
  419.             goto quit;
  420.         }
  421.     }
  422.     else    {
  423.                 SockPuts(Inst,Socket,"\nUser does not exist or has not telnet access to this machine.\nClosing connection\n");
  424.                 CloseSocket(Socket);
  425.                 goto quit;
  426.         }
  427.  
  428.     sprintf(MyPrgName, "telnetd <%s>", Info->Login);
  429.     SetProgramName(MyPrgName);
  430.  
  431.         if (Info->Command[0]=='*') {
  432.                 /* Use stdin/stdout */
  433.                 /* Make myself a filehandle */
  434. #ifdef DEBUG
  435.                 FPuts(DebugFile,"Logged in OK\nMaking Filehandle\n");
  436. #endif
  437.  
  438.                 FH=MyAllocDosObjectTags(Inst,DOS_FILEHANDLE,ADO_FH_Mode,MODE_OLDFILE,TAG_END);
  439.                 if (!FH) goto quit;
  440.                 FH->fh_Pos=FH->fh_End=-1;
  441.                 FH->fh_Type=&((struct Process *)FindTask(NULL))->pr_MsgPort;
  442.                 FH->fh_Args=(LONG)Info;
  443.                 FH->fh_Port=FH->fh_Type; /* Is this right? */
  444.                 FH=(struct FileHandle *)MKBADDR(FH);
  445.                 OpenCount++;
  446.  
  447.                 /* Run the subprocess */
  448.                 MakeLongStr(Buf,(ULONG)FH);
  449.                 strcpy(Buf+strlen(Buf)," ");
  450.                 strcpy(Buf+strlen(Buf),Info->Command+1 /* ignore the leading '*' */);
  451. #ifdef DEBUG
  452.                 FPuts(DebugFile,"Starting subprocess\nCmdLine=");
  453.                 FPuts(DebugFile,Buf);
  454.                 FPuts(DebugFile,"\n");
  455.                 /*Close(DebugFile);*/
  456.                 Flush(DebugFile);
  457.  
  458.                 /*DebugFile=NULL;*/
  459. #endif
  460.  
  461.                 /* NO more DOS calls allowed after this one */
  462.                 /* We also can't use Buf after we make this call */
  463.     if (*(Info->Command+1)) {
  464.                 MyCreateNewProcTags(Inst,NP_Entry,SubSubProc,
  465.                     NP_Arguments,Buf,
  466.                     TAG_END);
  467.     }
  468.                 FD_ZERO(&RdSet);
  469.                 IoctlSocket(Socket,FIONBIO,(caddr_t)&yes);
  470. #ifdef DEBUG
  471.                 PktFPuts(Inst,DebugFile,"Starting handler support\n");
  472. #endif
  473.                 for (;;) {
  474.                         if (ReadWaitList.lh_Head->ln_Succ && !HangupFlag) {
  475.                                 if (NextChar != -1) {
  476.                                         Pkt=PktFromMsg((struct Message *)ReadWaitList.lh_Head);
  477.                                         *(((unsigned char *)Pkt->dp_Arg2)+Pkt->dp_Res1)=NextChar;
  478.                                         Chr=NextChar;
  479.                                         NextChar=-1;
  480.                                         Err=1;
  481.                                         Pkt->dp_Res1++;
  482.                                         if (Pkt->dp_Res1==Pkt->dp_Arg3 || Chr=='\r' || Chr=='\n') {
  483.                                                 Remove(ReadWaitList.lh_Head);
  484.                                                 PutMsg(Pkt->dp_Port,Pkt->dp_Link); /* Send it back */
  485.                                         }
  486.                                 }
  487.                         }
  488.                         if (ReadWaitList.lh_Head->ln_Succ && !HangupFlag) {
  489.                                 FD_SET(Socket,&RdSet);
  490.                         } else {
  491.                                 FD_CLR(Socket,&RdSet);
  492.                         }
  493.                         SigMask=(1<<((struct Process *)FindTask(NULL))->pr_MsgPort.mp_SigBit)|(1<<TimePort->mp_SigBit);
  494.                         WaitSelect(Socket+1,&RdSet,NULL,NULL,NULL,&SigMask);
  495. #ifdef DEBUG
  496.                         PktFPuts(Inst,DebugFile,"Wait ended \n");
  497. #endif
  498.  
  499.                         if (FD_ISSET(Socket,&RdSet)) {
  500. #ifdef DEBUG
  501.                                 PktFPuts(Inst,DebugFile,"Got read available from socket\n");
  502. #endif
  503.                                 if (ReadWaitList.lh_Head->ln_Succ) {
  504.                                         /* Someone is waiting to read */
  505.                                         Pkt=PktFromMsg((struct Message *)ReadWaitList.lh_Head);
  506.                                         if (Pkt && Pkt->dp_Type==ACTION_READ) {
  507. #ifdef DEBUG
  508.                                                 PktFPuts(Inst,DebugFile,"Performing delayed read\n");
  509. #endif
  510.                                                 while (Pkt->dp_Res1 < Pkt->dp_Arg3) {
  511.                                                         if (NextChar != -1) {
  512.                                                                 *(((unsigned char *)Pkt->dp_Arg2)+Pkt->dp_Res1)=NextChar;
  513.                                                                 Chr=NextChar;
  514.                                                                 NextChar=-1;
  515.                                                                 Err=1;
  516.                                                         } else {
  517.                                                                 Err=RecvChar(Inst,Socket,((char *)Pkt->dp_Arg2)+Pkt->dp_Res1,FALSE/*RawMode*/);
  518.                                                                 Chr=*(((char *)Pkt->dp_Arg2)+Pkt->dp_Res1);
  519.                                                         }
  520.                                                         if (Err==1) Pkt->dp_Res1++;
  521.                                                         else if (Err==0) {
  522.                                                                 /* Hangup */
  523.                                                                 HangupFlag=TRUE;
  524.                                                                 break;
  525.                                                         } else break;
  526. #ifdef DEBUG
  527.                                                         if (Chr==255) {
  528.                                                                 PktFPuts(Inst,DebugFile,"Received 255\n");
  529.                                                         }
  530. #endif
  531.                                                         if (Chr=='\r' || Chr=='\n') {
  532.                                                                 break;
  533.                                                         }
  534.                                                 }
  535.                                                 if (Err==1) {
  536.                                                         if (Pkt->dp_Res1==Pkt->dp_Arg3 ||
  537.                                 Chr=='\r' || Chr=='\n') {
  538.                                                                 Remove(ReadWaitList.lh_Head);
  539. /*                                 syslog(LOG_DEBUG, "Sending out \"%s\"",
  540.  *                                        &Pkt->dp_Link+sizeof(struct Message));
  541.  */
  542.                                                                 PutMsg(Pkt->dp_Port,Pkt->dp_Link); /* Send it back */
  543.                                                         }
  544.                                                 }
  545.                                         } else if (Pkt && Pkt->dp_Type==ACTION_WAIT_CHAR) {
  546. #ifdef DEBUG
  547.                                                 PktFPuts(Inst,DebugFile,"Processing WAIT_CHAR");
  548. #endif
  549.                                                 if (NextChar==-1) {
  550.                                                         Err=RecvChar(Inst,Socket,&Chr,FALSE);
  551.                                                         if (Err==1) {
  552.                                                                 Pkt->dp_Res1=DOSTRUE;
  553.                                                                 Remove(ReadWaitList.lh_Head);
  554. #ifdef DEBUG
  555.                                                                 PktFPuts(Inst,DebugFile,"char ready\n");
  556. #endif
  557.                                                                 AbortIO((struct IORequest *)Pkt->dp_Res2);
  558.                                                                 WaitIO((struct IORequest *)Pkt->dp_Res2);
  559.                                                                 CloseDevice((struct IORequest *)Pkt->dp_Res2);
  560.                                                                 DeleteIORequest((struct IORequest *)Pkt->dp_Res2);
  561.                                                                 Pkt->dp_Res2=0;
  562.                                                                 PutMsg(Pkt->dp_Port,Pkt->dp_Link);
  563.                                                                 NextChar=Chr;
  564.                                                         } else {
  565. #ifdef DEBUG
  566.                                                                 PktFPuts(Inst,DebugFile,"no char available\n");
  567. #endif
  568.                                                                 NextChar=-1;
  569.                                                         }
  570.                                                         if (Err==0) HangupFlag=TRUE;
  571.                                                 } else {
  572.                                                         Pkt->dp_Res1=DOSTRUE;
  573.                                                         Remove(ReadWaitList.lh_Head);
  574.                                                         AbortIO((struct IORequest *)Pkt->dp_Res2);
  575.                                                         WaitIO((struct IORequest *)Pkt->dp_Res2);
  576.                                                         CloseDevice((struct IORequest *)Pkt->dp_Res2);
  577.                                                         DeleteIORequest((struct IORequest *)Pkt->dp_Res2);
  578.                                                         Pkt->dp_Res2=0;
  579.                                                         PutMsg(Pkt->dp_Port,Pkt->dp_Link);
  580. #ifdef DEBUG
  581.                                                         PktFPuts(Inst,DebugFile,"char ready\n");
  582. #endif
  583.                                                 }
  584.                                         }
  585.                                         else { /* Invalid message */
  586.                                                 Remove(ReadWaitList.lh_Head);
  587.                                         }
  588.                                 } else {
  589. #ifdef DEBUG
  590.                                         PktFPuts(Inst,DebugFile,"Unexpected: got read ready, no request\n");
  591. #endif
  592.                                 }
  593.                         }
  594.                         while (TimeReq=(struct timerequest *)GetMsg(TimePort)) {
  595.                                 Msg=(struct Message *)TimeReq->tr_node.io_Message.mn_Node.ln_Name;
  596.                                 Pkt=PktFromMsg(Msg);
  597.                                 CloseDevice(TimeReq);
  598.                                 DeleteIORequest(TimeReq);
  599.                                 Pkt->dp_Res1=DOSFALSE;
  600.                                 Pkt->dp_Res2=0;
  601.                                 Remove(Msg); /* Remove it from the read wait list */
  602.                                 PutMsg(Pkt->dp_Port,Pkt->dp_Link);
  603.  
  604.  
  605.                         }
  606.                         while (Msg=GetMsg(&((struct Process *)FindTask(NULL))->pr_MsgPort)) {
  607.                                 Pkt=PktFromMsg(Msg);
  608. #ifdef DEBUG
  609.                                 PktFPuts(Inst,DebugFile,"Got packet\n");
  610. #endif
  611.                                 switch(Pkt->dp_Type) {
  612.                                         case ACTION_FINDINPUT:
  613.                                         case ACTION_FINDOUTPUT:
  614.                                         case ACTION_FINDUPDATE:
  615.                                                 FH=(struct FileHandle *)BADDR((BPTR)Pkt->dp_Arg1);
  616.                                                 FH->fh_Pos=FH->fh_End=-1;
  617.                                                 FH->fh_Type=&((struct Process *)FindTask(NULL))->pr_MsgPort;
  618.                                                 FH->fh_Args=(LONG)Info;
  619.                                                 FH->fh_Port=FH->fh_Type; /* Is this right? */
  620.                                                 OpenCount++;
  621.                                                 Pkt->dp_Res1=DOSTRUE;
  622.                                                 PutMsg(Pkt->dp_Port,Pkt->dp_Link);
  623.                                         break;
  624.  
  625.                                         case ACTION_READ:
  626.                                         Pkt->dp_Res1=0;
  627. #ifdef DEBUG
  628.                                         PktFPuts(Inst,DebugFile,"Got action_read\n");
  629. #endif
  630.                                         AddTail(&ReadWaitList,Msg);
  631.                                         break;
  632.  
  633.                                         case ACTION_WRITE:
  634. #ifdef DEBUG
  635.                                         PktFPuts(Inst,DebugFile,"Got action_write\n");
  636. #endif
  637.                                         SockWrite(Inst,Socket,(char *)Pkt->dp_Arg2,Pkt->dp_Arg3,FALSE/*RawMode*/);
  638.                                         Pkt->dp_Res1=Pkt->dp_Arg3;
  639.                                         PutMsg(Pkt->dp_Port,Pkt->dp_Link);
  640.                                         break;
  641.  
  642.                                         case ACTION_WAIT_CHAR:
  643. #ifdef DEBUG
  644.                                                 PktFPuts(Inst,DebugFile,"Got action_waitchar");
  645. #endif
  646.                                                 Pkt->dp_Res1=DOSFALSE;
  647.  
  648.                                                 TimeReq=CreateIORequest(TimePort,sizeof(struct timerequest));
  649.                                                 if (!TimeReq || OpenDevice("timer.device",UNIT_MICROHZ,TimeReq,0)) {
  650.                                                         if (TimeReq)
  651.                               DeleteIORequest(TimeReq);
  652.                                                         Pkt->dp_Res2=ERROR_NO_FREE_STORE;
  653.                                                         PutMsg(Pkt->dp_Port,Pkt->dp_Link);
  654.                                                 }
  655.                                                 TimeReq->tr_node.io_Command=TR_ADDREQUEST;
  656.                                                 TimeReq->tr_time.tv_micro=Pkt->dp_Arg1;
  657.                                                 TimeReq->tr_time.tv_secs=0;
  658.                                                 TimeReq->tr_node.io_Message.mn_Node.ln_Name=Msg;
  659.                                                 SendIO(TimeReq);
  660.                                                 Pkt->dp_Res2=(ULONG)TimeReq;
  661.  
  662.                                                 AddTail(&ReadWaitList,Msg);
  663.  
  664.                                         break;
  665.  
  666.         /*
  667.                                         case ACTION_DISKINFO:
  668.  
  669.                                         break;
  670.                                         */
  671.                                         case ACTION_SCREEN_MODE:
  672. #ifdef DEBUG
  673.                                         PktFPuts(Inst,DebugFile,"Got action_screen_mode\n");
  674. #endif
  675.                                                 if (Pkt->dp_Arg1) {
  676.                                                         /* Raw mode */
  677.                                                         SockPuts(Inst,Socket,NoEcho);
  678.                                                         RawMode=TRUE;
  679.                                                 } else {
  680.                                                         SockPuts(Inst,Socket,Echo);
  681.                                                         RawMode=FALSE;
  682.                                                 }
  683.                                                 Pkt->dp_Res1=DOSFALSE;
  684.                                                 PutMsg(Pkt->dp_Port,Pkt->dp_Link);
  685.                                         break;
  686.  
  687.                                         case ACTION_END:
  688. #ifdef DEBUG
  689.                                         PktFPuts(Inst,DebugFile,"Got action_end\n");
  690. #endif
  691.                                                 Pkt->dp_Res1=0;
  692.                                                 PutMsg(Pkt->dp_Port,Pkt->dp_Link);
  693.                                                 OpenCount--;
  694.                                                 if (!OpenCount) {
  695.                                                         for (GotMsg=(struct Message *)ReadWaitList.lh_Head;GotMsg->mn_Node.ln_Succ;GotMsg=(struct Message *)GotMsg->mn_Node.ln_Succ) {
  696.                                                                 Pkt=PktFromMsg(GotMsg);
  697.                                                                 if (Pkt->dp_Type==ACTION_WAIT_CHAR) {
  698.                                                                         AbortIO((struct IORequest *)Pkt->dp_Res2);
  699.                                                                         WaitIO((struct IORequest *)Pkt->dp_Res2);
  700.                                                                         CloseDevice((struct IORequest *)Pkt->dp_Res2);
  701.                                                                         DeleteIORequest((struct IORequest *)Pkt->dp_Res2);
  702.                                                                         Pkt->dp_Res2=0;
  703.                                                                 }
  704.                                                         }
  705.  
  706.                                                         goto quit;
  707.                                                 }
  708.                                         break;
  709.  
  710.                                         case ACTION_SEEK:
  711. #ifdef DEBUG
  712.                                         PktFPuts(Inst,DebugFile,"Got action_seek\n");
  713. #endif
  714.                                         Pkt->dp_Res1=-1;
  715.                                         Pkt->dp_Res2=ERROR_OBJECT_WRONG_TYPE;
  716.                                         PutMsg(Pkt->dp_Port,Pkt->dp_Link);
  717.  
  718.                                         break;
  719.  
  720.  
  721.                                         default:
  722. #ifdef DEBUG
  723.                                         PktFPuts(Inst,DebugFile,"Got action_not_known. Number");
  724.                                         MakeLongStr(NumBuf,Pkt->dp_Type);
  725.                                         PktFPuts(Inst,DebugFile,NumBuf);
  726.                                         PktFPuts(Inst,DebugFile,"\n");
  727. #endif
  728.                                         Pkt->dp_Res1=0;
  729.                                         Pkt->dp_Res2=ERROR_ACTION_NOT_KNOWN;
  730.                                         PutMsg(Pkt->dp_Port,Pkt->dp_Link);
  731.                                 }
  732.                         }
  733.                 }
  734.         } else {
  735.                 /* Use fake serial */
  736.                 struct IOStdReq *IOReq=NULL;
  737.                 struct MsgPort *IOPort=NULL;
  738.                 struct FSRUnit *SerUnit=NULL;
  739.                 /* SerUnit->fsru_UserData[0]=CmdPort
  740.                    SerUnit->fsru_UserData[1]=ReadQueue
  741.                          SerUnit->fsru_UserData[2]=WriteQueue
  742.                          SerUnit->fsru_UserData[3]=Open count
  743.                          SerUnit->fsru_UserData[4]=RBufLen */
  744.                 struct MsgPort *CmdPort=NULL;
  745.                 struct List *ReadQueue=NULL;
  746.                 struct List *WriteQueue=NULL;
  747.                 char *CmdPtr;
  748.                 struct IOExtSer *GotReq=NULL,*OtrReq=NULL;
  749.                 char *RBuf=NULL;
  750.                 int RBufPos=0;
  751.                 int SerUnitAdded=FALSE;
  752.                 int Amnt;
  753.                 int RecvRet;
  754.                 int CD=TRUE; /* Carrier Detect */
  755.                 long UnitNum=FSR_UNITNONE;
  756.  
  757.                 /* We use IOExtSer.Status bit 0 as a flag to say whether this request has
  758.                    been aborted */
  759.  
  760. #ifdef DEBUG
  761.                 FPuts(DebugFile,"Creating ports...\n");
  762. #endif
  763.                 IOPort=CreateMsgPort();
  764.                 CmdPort=CreateMsgPort();
  765.                 IOReq=CreateIORequest(IOPort,sizeof(struct IOStdReq));
  766.                 if (!IOPort || !IOReq || !CmdPort) {
  767. #ifdef DEBUG
  768.                         FPuts(DebugFile,"Unable to create message port/IORequest\nExiting\n");
  769. #endif
  770.                         goto quitfakeser;
  771.                 }
  772. #ifdef DEBUG
  773.                 FPuts(DebugFile,"Opening fakesr.device...\n");
  774. #endif
  775.                 if (OpenDevice("fakesr.device",FSR_CTLUNIT,IOReq,0)) {
  776.                         IOReq->io_Device=NULL;
  777. #ifdef DEBUG
  778.                         FPuts(DebugFile,"Unable to open fakesr.device\nExiting\n");
  779. #endif
  780.                         goto quitfakeser;
  781.                 }
  782. #ifdef DEBUG
  783.                 FPuts(DebugFile,"opened successfully\n");
  784. #endif
  785.                 SerUnit=AllocMem(sizeof(struct FSRUnit),MEMF_CLEAR|MEMF_PUBLIC);
  786.                 ReadQueue=AllocMem(sizeof(struct List),MEMF_PUBLIC);
  787.                 if (ReadQueue) NewList(ReadQueue);
  788.                 WriteQueue=AllocMem(sizeof(struct List),MEMF_PUBLIC);
  789.                 if (WriteQueue) NewList(WriteQueue);
  790.                 if (!SerUnit || !ReadQueue || !WriteQueue) {
  791. #ifdef DEBUG
  792.                         FPuts(DebugFile,"Unable to allocate memory\nExiting\n");
  793. #endif
  794.                         goto quitfakeser;
  795.                 }
  796.  
  797.                 CmdPtr=Info->Command;
  798.                 if (Info->Command[0]<='9' && Info->Command[0] >= '0') {
  799.                         UnitNum=GetInt(Info->Command,&CmdPtr);
  800.                 }
  801.  
  802.                 SerUnit->fsru_Num=UnitNum;
  803.                 SerUnit->fsru_BeginIO=FakeBeginIO;
  804.                 SerUnit->fsru_AbortIO=FakeAbortIO;
  805.                 SerUnit->fsru_Open=FakeOpen;
  806.                 SerUnit->fsru_Close=FakeClose;
  807.                 SerUnit->fsru_UserData[0]=CmdPort;
  808.                 SerUnit->fsru_UserData[1]=ReadQueue;
  809.                 SerUnit->fsru_UserData[2]=WriteQueue;
  810.                 SerUnit->fsru_UserData[3]=0;
  811.                 SerUnit->fsru_UserData[4]=(void *)1024;
  812.  
  813.                 IOReq->io_Data=(APTR)SerUnit;
  814.                 IOReq->io_Length=sizeof(*SerUnit);
  815.                 IOReq->io_Command=FSRCMD_ADDUNIT;
  816.                 IOReq->io_Error=0;
  817. #ifdef DEBUG
  818.                 FPuts(DebugFile,"Adding FakeSr unit...");
  819. #endif
  820.  
  821.                 DoIO(IOReq);
  822.                 if (IOReq->io_Error) {
  823. #ifdef DEBUG
  824.                         FPuts(DebugFile,"Error adding fakesr.device unit\nExiting\n");
  825. #endif
  826.                         goto quitfakeser;
  827.                 }
  828.  
  829.                 SerUnitAdded=TRUE;
  830.  
  831. #ifdef DEBUG
  832.                 FPuts(DebugFile,"Done\n");
  833. #endif
  834.  
  835.                 RBuf=AllocMem((ULONG)SerUnit->fsru_UserData[4],MEMF_PUBLIC);
  836.                 RBufPos=0;
  837.                 if (!RBuf) {
  838. #ifdef DEBUG
  839.                         FPuts(DebugFile,"Unable to allocate memory\nExiting\n");
  840. #endif
  841.                         goto quitfakeser;
  842.                 }
  843.  
  844.  
  845.                 IoctlSocket(Socket,FIONBIO,(caddr_t)&yes);
  846.                 {
  847.                         BPTR NilInput,NilOutput;
  848. #ifdef DEBUG
  849.                         FPuts(DebugFile,"Opening filehandles\n");
  850. #endif
  851.       if (*CmdPtr) {
  852.                           NilInput=Open("NIL:",MODE_OLDFILE);
  853.                           NilOutput=Open("NIL:",MODE_OLDFILE);
  854.  
  855.                           /* sprintf(Buf,"%s -DEVICE fakesr.device -UNIT %ld",CmdPtr,SerUnit->fsru_Num); */
  856.                           strcpy(Buf,CmdPtr);
  857.                           mystrcat(Buf," -DEVICE fakesr.device -UNIT ");
  858.                           MakeLongStr(LoginBuf,SerUnit->fsru_Num);
  859. #ifdef DEBUG
  860.                           FPuts(DebugFile,"Got FakeSr unit: ");
  861.                           FPuts(DebugFile,LoginBuf);
  862.                           FPuts(DebugFile,"\n");
  863. #endif
  864.                           SockPuts(Inst,Socket,NoEcho);
  865.  
  866.                           mystrcat(Buf,LoginBuf);
  867. #ifdef DEBUG
  868.                           FPuts(DebugFile,"Running command:");
  869.                           FPuts(DebugFile,Buf);
  870.                           FPuts(DebugFile,"\n");
  871. #endif
  872.                           MySystemTags(DOSBase,Buf,SYS_Input,NilInput,SYS_Output,NilOutput,SYS_Asynch,TRUE,TAG_END);
  873.       }
  874.                 }
  875.  
  876.                 for (;;) {
  877.                         FD_ZERO(&RdSet);
  878.                         FD_ZERO(&WrSet);
  879.                         if (CD)  {
  880.                                 if (RBufPos < (((long)SerUnit->fsru_UserData[4])-1)) FD_SET(Socket,&RdSet);
  881.                                 if (WriteQueue->lh_Head->ln_Succ) FD_SET(Socket,&WrSet);
  882.                         }
  883.                         SigMask=(1<<CmdPort->mp_SigBit)|SIGBREAKF_CTRL_C;
  884.                         WaitSelect(Socket+1,&RdSet,&WrSet,NULL,NULL,&SigMask);
  885. #ifdef DEBUG
  886.                         FPuts(DebugFile,"Wait ended...");
  887. #endif
  888.  
  889.                         if (FD_ISSET(Socket,&RdSet)) {
  890.                                 while ((RBufPos < (long)SerUnit->fsru_UserData[4]) && ((RecvRet=RecvChar(Inst,Socket,RBuf+RBufPos,TRUE))==1)) RBufPos++;
  891.                                 Forbid();
  892.                                 if ((GotReq=(struct IOExtSer *)ReadQueue->lh_Head)->IOSer.io_Message.mn_Node.ln_Succ) {
  893.                                         Remove(GotReq);
  894.                                         Permit();
  895.                                         Amnt=min(RBufPos,GotReq->IOSer.io_Length);
  896.                                         memcpy(((char *)GotReq->IOSer.io_Data)+GotReq->IOSer.io_Actual,RBuf,Amnt);
  897.                                         GotReq->IOSer.io_Actual+=Amnt;
  898.                                         if (Amnt < RBufPos) mymovmem(RBuf+Amnt,RBuf,RBufPos-Amnt);
  899.                                         RBufPos-=Amnt;
  900.  
  901.                                         if (GotReq->IOSer.io_Actual < GotReq->IOSer.io_Length) {
  902.                                                 if (GotReq->io_Status & (1<<0)) {
  903.                                                         /* We got an AbortIO() */
  904.                                                         GotReq->IOSer.io_Error=IOERR_ABORTED;
  905.                                                         ReplyMsg(GotReq);
  906.                                                 } else {
  907.                                                         Forbid();
  908.                                                         AddTail(ReadQueue,GotReq);
  909.                                                         Permit();
  910.                                                 }
  911.                                         }
  912.                                         else ReplyMsg(GotReq);
  913.  
  914.                                 }
  915.                                 else Permit();
  916.                                 if (RecvRet==0) {
  917.                                         /* Connection closed */
  918.                                         CD=FALSE;
  919.                                 }
  920.                         }
  921.                         if (FD_ISSET(Socket,&WrSet)) {
  922.                                 Forbid();
  923.                                 if ((GotReq=(struct IOExtSer *)WriteQueue->lh_Head)->IOSer.io_Message.mn_Node.ln_Succ) {
  924.                                         Remove(GotReq);
  925.                                         Permit();
  926.  
  927. #ifdef DEBUG
  928.                                         FPuts(DebugFile,"Writing to socket\n");
  929.                                         MyFPrintf(Inst,DebugFile,"io_Actual=%ld,io_Length=%ld\n",(long)GotReq->IOSer.io_Actual,(long)GotReq->IOSer.io_Length);
  930. #endif
  931.                                         SockWrite(Inst,Socket,((char *)GotReq->IOSer.io_Data)+GotReq->IOSer.io_Actual,GotReq->IOSer.io_Length-GotReq->IOSer.io_Actual,TRUE);
  932. #ifdef DEBUG
  933.                                         FPuts(DebugFile,"Write completed\n");
  934. #endif
  935.                                         GotReq->IOSer.io_Actual=GotReq->IOSer.io_Length;
  936.  
  937.  
  938.                                         if (GotReq->IOSer.io_Actual < GotReq->IOSer.io_Length) {
  939.                                                 Forbid();
  940.                                                 if (GotReq->io_Status & (1<<0)) {
  941.                                                         Permit();
  942.                                                         /* We got an AbortIO() */
  943.                                                         GotReq->IOSer.io_Error=IOERR_ABORTED;
  944.                                                         ReplyMsg(GotReq);
  945.                                                 } else {
  946.                                                         AddTail(WriteQueue,GotReq);
  947.                                                         Permit();
  948.                                                 }
  949.                                         } else {
  950. #ifdef DEBUG
  951.                                                 FPuts(DebugFile,"Replying write message\n");
  952. #endif
  953.                                                 ReplyMsg(GotReq);
  954.                                         }
  955.  
  956.  
  957.                                 } else {
  958.  
  959.                                         Permit();
  960.                                 }
  961.                         }
  962.                         while (GotReq=(struct IOExtSer *)GetMsg(CmdPort)) {
  963.                                 if (GotReq->IOSer.io_Message.mn_Node.ln_Name==Signature) {
  964.                                         /* We just use the pointer as a signature */
  965.                                         /* We just got an expunge request */
  966. #ifdef DEBUG
  967.                                         FPuts(DebugFile,"Got expunge request\n");
  968. #endif
  969.  
  970.                                         FreeMem(GotReq,sizeof(struct Message)); /* We free the expunge request instead of reply */
  971.  
  972.                                         Forbid();
  973.                                         if (SerUnit->fsru_UserData[3]==0) {
  974.                                                 /* Open count==0 */
  975.                                                 if (SerUnitAdded) {
  976.                                                         IOReq->io_Command=FSRCMD_REMUNIT;
  977.                                                         IOReq->io_Data=(APTR)SerUnit;
  978.                                                         IOReq->io_Length=sizeof(*SerUnit);
  979.                                                         DoIO(IOReq);
  980.                                                         SerUnitAdded=FALSE;
  981.                                                 }
  982.                                                 if (SerUnit->fsru_UserData[3]==0) {
  983.                                                         /* If opencnt is still 0 */
  984.                                                         Permit();
  985.                                                         goto quitfakeser; /* exit */
  986.                                                 }
  987.                                         }
  988.                                         Permit();
  989.                                 }
  990.                                 else {
  991. #ifdef DEBUG
  992.                                         FPuts(DebugFile,"Got cmd...");
  993. #endif
  994.  
  995.                                         switch(GotReq->IOSer.io_Command) {
  996.                                                 case CMD_CLEAR:
  997. #ifdef DEBUG
  998.                                                         FPuts(DebugFile,"Got CMD_CLEAR\n");
  999. #endif
  1000.                                                         RBufPos=0;
  1001.                                                         GotReq->IOSer.io_Error=0;
  1002.                                                         ReplyMsg(GotReq);
  1003.                                                 break;
  1004.  
  1005.                                                 case CMD_FLUSH:
  1006.                                                 case CMD_RESET:
  1007. #ifdef DEBUG
  1008.                                                         FPuts(DebugFile,"Got CMD_FLUSH/RESET\n");
  1009. #endif
  1010.  
  1011.                                                         Forbid();
  1012.                                                         while (OtrReq=(struct IOExtSer *)RemHead(ReadQueue)) {
  1013.                                                                 OtrReq->IOSer.io_Error=IOERR_ABORTED;
  1014.                                                                 ReplyMsg(OtrReq);
  1015.                                                         }
  1016.                                                         while (OtrReq=(struct IOExtSer *)RemHead(WriteQueue)) {
  1017.                                                                 OtrReq->IOSer.io_Error=IOERR_ABORTED;
  1018.                                                                 ReplyMsg(OtrReq);
  1019.                                                         }
  1020.                                                         Permit();
  1021.                                                         GotReq->IOSer.io_Error=0;
  1022.                                                         ReplyMsg(GotReq);
  1023.                                                 break;
  1024.  
  1025.                                                 case CMD_READ:
  1026. #ifdef DEBUG
  1027.                                                         FPuts(DebugFile,"Got CMD_READ\n");
  1028. #endif
  1029.  
  1030.                                                         GotReq->IOSer.io_Actual=0;
  1031.                                                         GotReq->IOSer.io_Error=0;
  1032.                                                         Amnt=min(RBufPos,GotReq->IOSer.io_Length);
  1033.                                                         memcpy(((char *)GotReq->IOSer.io_Data)+GotReq->IOSer.io_Actual,RBuf,Amnt);
  1034.                                                         GotReq->IOSer.io_Actual+=Amnt;
  1035.                                                         if (Amnt < RBufPos) mymovmem(RBuf+Amnt,RBuf,Amnt);
  1036.                                                         RBufPos-=Amnt;
  1037.  
  1038.                                                         if (GotReq->IOSer.io_Actual < GotReq->IOSer.io_Length) {
  1039.                                                                 Forbid();
  1040.                                                                 AddTail(ReadQueue,GotReq);
  1041.                                                                 Permit();
  1042.                                                         }
  1043.                                                         else ReplyMsg(GotReq);
  1044.                                                 break;
  1045.  
  1046.                                                 case CMD_START:
  1047. #ifdef DEBUG
  1048.                                                         FPuts(DebugFile,"Got CMD_START\n");
  1049. #endif
  1050.  
  1051.                                                         GotReq->IOSer.io_Error=0;
  1052.                                                         ReplyMsg(GotReq);
  1053.                                                 break;
  1054.  
  1055.                                                 case CMD_STOP:
  1056. #ifdef DEBUG
  1057.                                                         FPuts(DebugFile,"Got CMD_STOP\n");
  1058. #endif
  1059.  
  1060.                                                         GotReq->IOSer.io_Error=0;
  1061.                                                         ReplyMsg(GotReq);
  1062.                                                 break;
  1063.  
  1064.                                                 case CMD_WRITE:
  1065. #ifdef DEBUG
  1066.                                                         FPuts(DebugFile,"Got CMD_WRITE\n");
  1067. #endif
  1068.  
  1069.                                                         GotReq->IOSer.io_Actual=0;
  1070.                                                         GotReq->IOSer.io_Error=0;
  1071.                                                         Forbid();
  1072.                                                         AddTail(WriteQueue,GotReq);
  1073.                                                         Permit();
  1074.                                                 break;
  1075.  
  1076.                                                 case SDCMD_BREAK:
  1077. #ifdef DEBUG
  1078.                                                         FPuts(DebugFile,"Got SDCMD_BREAK\n");
  1079. #endif
  1080.  
  1081.                                                         GotReq->IOSer.io_Error=0;
  1082.                                                         ReplyMsg(GotReq);
  1083.                                                 break;
  1084.  
  1085.                                                 case SDCMD_QUERY:
  1086. #ifdef DEBUG
  1087.                                                         FPuts(DebugFile,"Got SDCMD_QUERY\n");
  1088. #endif
  1089.  
  1090.                                                         GotReq->IOSer.io_Actual=RBufPos;
  1091.                                                         GotReq->io_Status=0x0000 | ((CD) ? 0:(1<<5));
  1092.                                                         GotReq->IOSer.io_Error=0;
  1093.  
  1094.                                                         ReplyMsg(GotReq);
  1095.                                                 break;
  1096.  
  1097.                                                 case SDCMD_SETPARAMS:
  1098. #ifdef DEBUG
  1099.                                                         FPuts(DebugFile,"Got SDCMD_SETPARAMS\n");
  1100. #endif
  1101.  
  1102.                                                         GotReq->IOSer.io_Error=0;
  1103.                                                         ReplyMsg(GotReq);
  1104.                                                 break;
  1105.  
  1106.                                                 default:
  1107. #ifdef DEBUG
  1108.                                                         FPuts(DebugFile,"Got CMD_UNKNOWN\n");
  1109. #endif
  1110.                                                         GotReq->IOSer.io_Error=IOERR_NOCMD;
  1111.                                                         ReplyMsg(GotReq);
  1112.  
  1113.                                         }
  1114.                                 }
  1115.                         }
  1116.                 }
  1117.  
  1118.  
  1119.                 quitfakeser:
  1120.  
  1121.                 if (ReadQueue) {
  1122.                         Forbid();
  1123.                         while (GotReq=(struct IOExtSer *)RemHead(ReadQueue)) {
  1124.                                 GotReq->IOSer.io_Error=IOERR_ABORTED;
  1125.                                 GotReq->IOSer.io_Actual=0;
  1126.                                 ReplyMsg(GotReq);
  1127.                         }
  1128.                         Permit();
  1129.                         FreeMem(ReadQueue,sizeof(struct List));
  1130.                 }
  1131.                 if (WriteQueue) {
  1132.                         Forbid();
  1133.                         while (GotReq=(struct IOExtSer *)RemHead(WriteQueue)) {
  1134.                                 GotReq->IOSer.io_Error=IOERR_ABORTED;
  1135.                                 GotReq->IOSer.io_Actual=0;
  1136.                                 ReplyMsg(GotReq);
  1137.                         }
  1138.                         Permit();
  1139.                         FreeMem(WriteQueue,sizeof(struct List));
  1140.                 }
  1141.                 if (RBuf && SerUnit) {
  1142.                         FreeMem(RBuf,(long)SerUnit->fsru_UserData[4]);
  1143.                 }
  1144.                 if (SerUnit) {
  1145.                         if (SerUnitAdded && IOReq) {
  1146.                                 IOReq->io_Data=(APTR)SerUnit;
  1147.                                 IOReq->io_Length=sizeof(*SerUnit);
  1148.                                 IOReq->io_Command=FSRCMD_REMUNIT;
  1149.                                 DoIO(IOReq);
  1150.                         }
  1151.                         FreeMem(SerUnit,sizeof(struct FSRUnit));
  1152.                 }
  1153.                 if (IOReq) {
  1154.                         if (IOReq->io_Device) CloseDevice(IOReq);
  1155.                         DeleteIORequest(IOReq);
  1156.                 }
  1157.                 if (IOPort) DeleteMsgPort(IOPort);
  1158.                 if (CmdPort) DeleteMsgPort(CmdPort);
  1159.                 goto quit;
  1160.         }
  1161.  
  1162.         quit:
  1163. #ifdef DEBUG
  1164.         if (DebugFile) Close(DebugFile);
  1165. #endif
  1166.         SocketBaseTags(SBTM_SETVAL(SBTC_LOGTAGPTR), NULL, TAG_END);
  1167.         if (TimePort) DeleteMsgPort(TimePort);
  1168.         if (Info) FreeMem(Info,sizeof(struct PasswdInfo));
  1169.     if (muInfo) muFreeUserInfo(muInfo); /* added by andsk */
  1170.         if (Inst) {
  1171.         if (muBase) CloseLibrary((struct Library *)muBase); /* added by andsk */
  1172.                 if (UserGroupBase) CloseLibrary(UserGroupBase);
  1173.                 if (SocketBase) CloseLibrary(SocketBase);
  1174.                 if (UtilityBase) CloseLibrary(UtilityBase);
  1175.                 if (DOSBase) CloseLibrary(DOSBase);
  1176.         }
  1177.         return 0;
  1178. }
  1179.  
  1180. void MyFPrintf(struct InstData *Inst,BPTR File,char *Fmt,...)
  1181. {
  1182.         VFPrintf(File,Fmt,(&Fmt)+1);
  1183. }
  1184.  
  1185. void mystrcat(char *Dest,char *Cat)
  1186. {
  1187.         memcpy(Dest+strlen(Dest),Cat,strlen(Cat)+1);
  1188. }
  1189.  
  1190. void mymovmem(char *From,char *To,int Len)
  1191. {
  1192.         int Cnt;
  1193.         if (From > To) {
  1194.                 for (Cnt=0;Cnt < Len;Cnt++) {
  1195.                         To[Cnt]=From[Cnt];
  1196.                 }
  1197.         } else if (From < To) {
  1198.                 for (Cnt=Len-1;Cnt >= 0;Cnt--) {
  1199.                         To[Cnt]=From[Cnt];
  1200.                 }
  1201.         }
  1202. }
  1203.  
  1204. struct Node *FindNode(struct List *List,struct Node *Node)
  1205. /* returns Node if Node is a member of list, NULL otherwise */
  1206. {
  1207.         struct Node *ChkNode;
  1208.  
  1209.         for (ChkNode=List->lh_Head;ChkNode->ln_Succ;ChkNode=ChkNode->ln_Succ) {
  1210.                 if (ChkNode==Node) return Node;
  1211.         }
  1212.         return NULL;
  1213. }
  1214.  
  1215. ULONG FakeBeginIO(void *IORequest)
  1216. {
  1217.         ((struct IORequest *)IORequest)->io_Flags &= ~IOF_QUICK; /* Quick IO not supported */
  1218.         ((struct IOExtSer *)IORequest)->io_Status &= ~(1<<0); /* clear abort bit */
  1219.         ((struct Node *)IORequest)->ln_Name=NULL; /* clear possible signature */
  1220.         PutMsg((struct MsgPort *)((struct FSRUnit *)((struct IORequest *)IORequest)->io_Unit)->fsru_UserData[0],IORequest);
  1221.         return 0;
  1222. }
  1223.  
  1224. ULONG FakeAbortIO(void *IORequest)
  1225. {
  1226.         struct IOExtSer *Ser;
  1227.  
  1228.         Ser=IORequest;
  1229.         Forbid();
  1230.                 Ser->io_Status |= (1<<0); /* Flag the request as aborted */
  1231.                 if (FindNode(((struct FSRUnit *)Ser->IOSer.io_Unit)->fsru_UserData[1],Ser) ||
  1232.                         FindNode(((struct FSRUnit *)Ser->IOSer.io_Unit)->fsru_UserData[2],Ser)) {
  1233.                                 /* This IORequest is waiting to be processed */
  1234.                                 Remove(Ser);
  1235.                                 Ser->IOSer.io_Error=IOERR_ABORTED;
  1236.                                 Ser->IOSer.io_Actual=0;
  1237.                                 ReplyMsg(Ser);
  1238.                 }
  1239.                 else {
  1240.                         /* This IORequest is currently being processed -- send a break */
  1241.                         Signal(((struct MsgPort *)((struct FSRUnit *)Ser->IOSer.io_Unit)->fsru_UserData[0])->mp_SigTask,SIGBREAKF_CTRL_C);
  1242.                 }
  1243.         Permit();
  1244.  
  1245.         return 0;
  1246. }
  1247.  
  1248. ULONG FakeOpen(void *IORequest)
  1249. {
  1250.         struct IOExtSer *Ser;
  1251.  
  1252.         Ser=IORequest;
  1253.         Forbid();
  1254.         ((struct FSRUnit *)Ser->IOSer.io_Unit)->fsru_UserData[3]=(void *) ((long)(((struct FSRUnit *)Ser->IOSer.io_Unit)->fsru_UserData[3])+1); /* Increment opencnt */
  1255.         Permit();
  1256.         Ser->IOSer.io_Error=0;
  1257.         Ser->io_CtlChar=SER_DEFAULT_CTLCHAR;
  1258.         Ser->io_RBufLen=(long)((struct FSRUnit *)Ser->IOSer.io_Unit)->fsru_UserData[4];
  1259.         Ser->io_ExtFlags=0;
  1260.         Ser->io_Baud=19200;
  1261.         Ser->io_BrkTime=250000;
  1262.         Ser->io_TermArray.TermArray0=0;
  1263.         Ser->io_TermArray.TermArray1=0;
  1264.         Ser->io_ReadLen=8;
  1265.         Ser->io_WriteLen=8;
  1266.         Ser->io_StopBits=1;
  1267.         Ser->io_Status=0;
  1268.         return 0;
  1269. }
  1270.  
  1271. ULONG FakeClose(void *IORequest)
  1272. {
  1273.         struct IOExtSer *Ser;
  1274.         struct Message *Msg;
  1275.  
  1276.         Ser=IORequest;
  1277.         Forbid();
  1278.  
  1279.         ((struct FSRUnit *)Ser->IOSer.io_Unit)->fsru_UserData[3]=(void *) ((long)(((struct FSRUnit *)Ser->IOSer.io_Unit)->fsru_UserData[3])-1); /* Decrement opencnt */
  1280.         Msg=AllocMem(sizeof(struct Message),MEMF_PUBLIC|MEMF_CLEAR);
  1281.         Msg->mn_Node.ln_Name=Signature;
  1282.         PutMsg((struct MsgPort *)((struct FSRUnit *)((struct IORequest *)IORequest)->io_Unit)->fsru_UserData[0],Msg);
  1283.  
  1284.         Permit();
  1285.         return 0;
  1286. }
  1287.  
  1288.  
  1289. struct DosPacket *PktFromMsg(struct Message *Msg)
  1290. {
  1291.         return (struct DosPacket *)Msg->mn_Node.ln_Name;
  1292. }
  1293.  
  1294. void PktFPuts(struct InstData *Inst,BPTR File,char *String)
  1295. {
  1296.         struct MsgPort *ReplyPort;
  1297.         struct DosPacket *Pkt;
  1298.  
  1299.         ReplyPort=CreateMsgPort();
  1300.         Pkt=AllocDosObject(DOS_STDPKT,NULL);
  1301.         if (!Pkt || !ReplyPort) return;
  1302.  
  1303.         Pkt->dp_Type=ACTION_WRITE;
  1304.         Pkt->dp_Arg1=((struct FileHandle *)BADDR(File))->fh_Arg1;
  1305.         Pkt->dp_Arg2=(LONG) String;
  1306.         Pkt->dp_Arg3=strlen(String);
  1307.         Pkt->dp_Port=ReplyPort;
  1308.         PutMsg(((struct FileHandle *)BADDR(File))->fh_Type,Pkt->dp_Link);
  1309.         WaitPort(ReplyPort);
  1310.         GetMsg(ReplyPort);
  1311.         DeleteMsgPort(ReplyPort);
  1312.         FreeDosObject(DOS_STDPKT,Pkt);
  1313. }
  1314.  
  1315. unsigned long GetInt(char *String,char **NewPtr)
  1316. {
  1317.         unsigned long Num=0;
  1318.         char *Junk;
  1319.         long Cnt;
  1320.         long BaseNum;
  1321.  
  1322.         if (!NewPtr) NewPtr=&Junk;
  1323.  
  1324.         for (*NewPtr=String;;(*NewPtr)++) {
  1325.  
  1326.                 if (**NewPtr < '0' || **NewPtr > '9') return Num;
  1327.  
  1328.                 /* AAARGH!! multiplication causes a lib call to be generated.
  1329.                    We can't use the library. Therefore we have to add */
  1330.                 /* Num=Num*10; */
  1331.                 for (BaseNum=Num,Cnt=0;Cnt < 9;Cnt++,Num+=BaseNum);
  1332.  
  1333.  
  1334.                 Num+=**NewPtr-'0';
  1335.         }
  1336.  
  1337. }
  1338.  
  1339.  
  1340. void SockPuts(struct InstData *Inst,int Sock,char *Buf)
  1341. {
  1342.         int BufPos=0;
  1343.         int BytesWritten;
  1344.  
  1345.         do {
  1346.                 BytesWritten=send(Sock,Buf+BufPos,strlen(Buf+BufPos),0);
  1347.                 if (BytesWritten > 0) BufPos+=BytesWritten;
  1348.         } while (Buf[BufPos]);
  1349. }
  1350.  
  1351. void SockRawWrite(struct InstData *Inst,int Sock,char *Buf,int Len)
  1352. {
  1353.         int BufPos=0;
  1354.         int BytesWritten;
  1355.  
  1356.         if (!Len) return;
  1357.  
  1358.         do {
  1359.                 BytesWritten=send(Sock,Buf+BufPos,Len-BufPos,0);
  1360.                 if (BytesWritten > 0) BufPos+=BytesWritten;
  1361.         } while (Len-BufPos);
  1362.  
  1363. }
  1364.  
  1365. void SockWrite(struct InstData *Inst,int Sock,char *Buf,int Len,int RawFlag)
  1366. {
  1367.         int Cnt;
  1368.         int BufPos=0;
  1369.         unsigned char iac2[2];
  1370.         char eol[2];
  1371.         char csi[2];
  1372.         iac2[0]=iac2[1]=IAC;
  1373.         eol[0]='\r';
  1374.         eol[1]='\n';
  1375.         csi[0]='\x1b';
  1376.         csi[1]='[';
  1377.  
  1378.  
  1379.         while (Len > BufPos) {
  1380.                 for (Cnt=BufPos;Cnt < Len;Cnt++) {
  1381.                         if (!RawFlag)
  1382.                                 if (Buf[Cnt]=='\r' || Buf[Cnt]=='\n') break;
  1383.                                 if (Buf[Cnt]=='\x9b') break;
  1384.                         if (Buf[Cnt]==IAC) {
  1385.                                 break;
  1386.                         }
  1387.                 }
  1388.                 SockRawWrite(Inst,Sock,Buf+BufPos,Cnt-BufPos);
  1389.                 BufPos=Cnt;
  1390.                 if (BufPos < Len && Buf[BufPos]==IAC) { /* If we got single IAC, send double IAC */
  1391.                         BufPos++;
  1392.                         SockRawWrite(Inst,Sock,iac2,2);
  1393.                 }
  1394.                 if (!RawFlag) {
  1395.                         if (BufPos < Len && Buf[BufPos]=='\r') {
  1396.                                 BufPos++;
  1397.                         }
  1398.                         if (BufPos < Len && Buf[BufPos]=='\n') {
  1399.                                 BufPos++;
  1400.                                 SockRawWrite(Inst,Sock,eol,2);
  1401.                         }
  1402.                         if (BufPos < Len && Buf[BufPos]=='\x9b') {
  1403.                                 BufPos++;
  1404.                                 SockRawWrite(Inst,Sock,csi,2);
  1405.                         }
  1406.                 }
  1407.         }
  1408. }
  1409.  
  1410. void ParseBuf3(struct InstData *Inst)
  1411. /* Parse 3 character remote request */
  1412. {
  1413.  
  1414. }
  1415.  
  1416. void ParseBuf2(struct InstData *Inst)
  1417. /* Parse 2 character remote-request */
  1418. {
  1419.  
  1420. }
  1421.  
  1422. void ParseBufSubNegotiate(struct InstData *Inst)
  1423. {
  1424.  
  1425. }
  1426.  
  1427. int RecvChar(struct InstData *Inst,int Sock,unsigned char *Loc,int RawMode)
  1428. {
  1429.         int GotLen;
  1430.         unsigned char Got,TrueGot;
  1431.         /*RawMode=TRUE;*/
  1432.         static unsigned char PrevChar;
  1433.  
  1434.         do {
  1435.  
  1436.                 GotLen=recv(Sock,&Got,1,0); /* Wait for a character */
  1437.                 if (GotLen==-1) {
  1438.                         if (Errno()==EINTR) continue;
  1439.                         else return -1;
  1440.                 } else if (GotLen==0) return 0;
  1441.  
  1442.                 TrueGot=Got;
  1443.                 if (!Inst->RecvBufPos && GotLen==1 && Got==0) GotLen=-1; /* Read again */
  1444.                 if (GotLen==1 && !RawMode && !Inst->RecvBufPos) {
  1445.                         /* These next few lines ignore incoming newlines and convert
  1446.                         incoming CRs into newlines   */
  1447.                         if (Got=='\n' && PrevChar=='\r') GotLen=-1; /* Read again. */
  1448.                         if (Got=='\r') Got='\n';
  1449.                 }
  1450.         } while (GotLen != 1);
  1451. /*      *Loc=Got;
  1452.         return 1; */
  1453.  
  1454.         if (Inst->RecvBufPos) {
  1455.                 Inst->RecvBuf[Inst->RecvBufPos]=Got;
  1456.                 Inst->RecvBufPos++;
  1457.                 switch (Inst->RecvBufPos) {
  1458.                         case 2:
  1459.                           switch(Inst->RecvBuf[1]) {
  1460.                                         case IAC:
  1461.                                           /* Just a single IAC */
  1462.                                                 *Loc=IAC;
  1463.                                                 return 1;
  1464.                                         break;
  1465.  
  1466.                                         case SB:
  1467.                                                 Inst->RecvBufFlags|=RBF_SUBNEGOTIATE;
  1468.                                                 return RecvChar(Inst,Sock,Loc,RawMode);
  1469.                                         break;
  1470.  
  1471.                                         case SE:
  1472.                                         Inst->RecvBufPos=0;
  1473.                                         Inst->RecvBufFlags &= ~RBF_SUBNEGOTIATE;
  1474.                                         return RecvChar(Inst,Sock,Loc,RawMode);
  1475.  
  1476.                                         case WILL:
  1477.                                         case WONT:
  1478.                                         case DO:
  1479.                                         case DONT:
  1480.                                         return RecvChar(Inst,Sock,Loc,RawMode);
  1481.                                         break;
  1482.  
  1483.                                         default:
  1484.                                         ParseBuf2(Inst);
  1485.                                         Inst->RecvBufPos=0;
  1486.                                         return RecvChar(Inst,Sock,Loc,RawMode);
  1487.                                 }
  1488.                         break;
  1489.  
  1490.                         default:
  1491.                                 if (Inst->RecvBufFlags & RBF_SUBNEGOTIATE) {
  1492.                                         if (Inst->RecvBufPos >= 2 && Inst->RecvBuf[Inst->RecvBufPos-2]==IAC && Inst->RecvBuf[Inst->RecvBufPos-1]!=IAC) {
  1493.                                                 /* End of subnegotiation */
  1494.                                                 Inst->RecvBuf[0]=IAC;
  1495.                                                 if ((Inst->RecvBuf[1]=Inst->RecvBuf[Inst->RecvBufPos-1])==SE) {
  1496.                                                         Inst->RecvBufFlags &= ~RBF_SUBNEGOTIATE;
  1497.                                                         Inst->RecvBufPos=0;
  1498.                                                         return RecvChar(Inst,Sock,Loc,RawMode);
  1499.                                                 }
  1500.                                                 Inst->RecvBufPos=2;
  1501.  
  1502.                                                 ParseBufSubNegotiate(Inst);
  1503.                                         }
  1504.  
  1505.                                         if (Inst->RecvBufPos >= 2 && Inst->RecvBuf[Inst->RecvBufPos-2]==IAC && Inst->RecvBuf[Inst->RecvBufPos-1]==IAC) {
  1506.                                                 /* We just got a double IAC in subnegotiation */
  1507.                                                 Inst->RecvBuf[Inst->RecvBufPos-2]=-1; /* We store IAC as a (int)-1 */
  1508.                                                 Inst->RecvBufPos--;
  1509.                                         }
  1510.                                         return RecvChar(Inst,Sock,Loc,RawMode);
  1511.                                 } else {
  1512.                                         if (Inst->RecvBuf[2]==IAC) {
  1513.                                                 /* Restart sequence */
  1514.                                                 Inst->RecvBuf[0]=IAC;
  1515.                                                 Inst->RecvBufPos=1;
  1516.                                                 return RecvChar(Inst,Sock,Loc,RawMode);
  1517.                                         } else {
  1518.                                           ParseBuf3(Inst);
  1519.                                                 Inst->RecvBufPos=0;
  1520.                                                 return RecvChar(Inst,Sock,Loc,RawMode);
  1521.                                         }
  1522.                                 }
  1523.                         break;
  1524.                 }
  1525.         }
  1526.         else {
  1527.                 if (Got==IAC) {
  1528.                         Inst->RecvBuf[0]=Got;
  1529.                         Inst->RecvBufPos=1;
  1530.                         return RecvChar(Inst,Sock,Loc,RawMode);
  1531.                 } else {
  1532.                         *Loc=Got;
  1533.                         PrevChar=TrueGot;
  1534.                         return 1;
  1535.                 }
  1536.         }
  1537.         return 1;
  1538.  
  1539. }
  1540.  
  1541.  
  1542. void SockGets(struct InstData *Inst,int Sock,char *Buf,int BufSize)
  1543. /* This function gets the next string until a CR
  1544. on the specified socket, and places it in buf. It
  1545. discards leading crs/lfs */
  1546. {
  1547.         int BufPos=0;
  1548.         int BytesRead;
  1549.         int FirstBytes=TRUE;
  1550.         Buf[0]='\0';
  1551.  
  1552.         do {
  1553.                 BytesRead=RecvChar(Inst,Sock,Buf+BufPos,FALSE);
  1554.                 if (BytesRead < 0) {
  1555.                         if (Errno()!=EINTR) {
  1556.                                 Buf[BufPos]='\0';
  1557.                                 return;
  1558.                         }
  1559.           }
  1560.                 else if (BytesRead==0) {
  1561.                         Buf[BufPos]='\0';
  1562.                         return;
  1563.                 }
  1564.                 else {
  1565.                         if ((Buf[BufPos]=='\r' || Buf[BufPos]=='\n') && FirstBytes) {
  1566.                                 Buf[BufPos]='\0';
  1567.                         } else {
  1568.                                 FirstBytes=FALSE;
  1569.                                 BufPos+=BytesRead;
  1570.                         }
  1571.                 }
  1572.         } while (Buf[BufPos-1] != '\r' && Buf[BufPos-1] != '\n' && BufPos < (BufSize-1));
  1573.         Buf[BufPos]='\0';
  1574. }
  1575.  
  1576. char *PullPasswdString(char **StringPtr)
  1577. {
  1578.         int Cnt;
  1579.         char *RetVal;
  1580.         char *CurPos;
  1581.  
  1582.         if (!StringPtr || !*StringPtr) return NULL;
  1583.  
  1584.         RetVal=*StringPtr;
  1585.  
  1586.         for (CurPos=RetVal;*CurPos != ',' && *CurPos != '\r' && *CurPos != '\n' && *CurPos;CurPos++);
  1587.         switch (*CurPos) {
  1588.                 case ',':
  1589.                 case '\r':
  1590.                 case '\n':
  1591.                         *CurPos='\0';
  1592.                         CurPos++;
  1593.                         *StringPtr=CurPos;
  1594.                 return RetVal;
  1595.  
  1596.                 case '\0':
  1597.                 *StringPtr=CurPos;
  1598.                 return RetVal;
  1599.         }
  1600. }
  1601.  
  1602. int mystrcmp(char *S1,char *S2)
  1603. {
  1604.         int Cnt;
  1605.         for (Cnt=0;S1[Cnt] && S2[Cnt];Cnt++) {
  1606.                 if (S1[Cnt] != S2[Cnt]) return !0;
  1607.         }
  1608.         if (S1[Cnt] != S2[Cnt]) return !0;
  1609.         return 0;
  1610. }
  1611.  
  1612. struct PasswdInfo *LookupPasswd(struct InstData *Inst,char *Login)
  1613. {
  1614.         BPTR File;
  1615.         char *LineBuf;
  1616.         char *BufPtr;
  1617.         char *PasswdPtr;
  1618.         char *LoginPtr;
  1619.         char *RealNamePtr;
  1620.         char *HomeDirPtr;
  1621.         char *CmdPtr;
  1622.         struct PasswdInfo *Info = NULL;
  1623.         struct passwd *result;
  1624.  
  1625.         if (result = getpwnam(Login)) {
  1626.                 if (Info=AllocMem(sizeof(struct PasswdInfo),MEMF_PUBLIC)) {
  1627.                         strcpy(Info->Login,result->pw_name);
  1628.                         strcpy(Info->Passwd,result->pw_passwd);
  1629.                         strcpy(Info->RealName,result->pw_gecos);
  1630.                         strcpy(Info->Command,result->pw_shell);
  1631.                 }
  1632.                 else
  1633.                         syslog(LOG_CRIT, "Couldn't allocate my info structure!");
  1634.         }
  1635.         else
  1636.         ;
  1637. /*                syslog(LOG_INFO, "user %s is unknown here", Login); */
  1638.  
  1639.         return Info;
  1640. }
  1641.  
  1642. void __asm PutMLSChar(register __d0 char Chr,register __a3 char **BufPtr)
  1643. {
  1644.         **BufPtr=Chr;
  1645.         (*BufPtr)++;
  1646. }
  1647.  
  1648. void MakeLongStr(char *StrBuf,unsigned long Num)
  1649. {
  1650.         RawDoFmt("%lu",&Num,PutMLSChar,&StrBuf);
  1651. }
  1652.  
  1653.  
  1654. struct Process *MyCreateNewProcTags(struct InstData *Inst,ULONG Tag1,...)
  1655. {
  1656.         return CreateNewProc((struct TagItem *)&Tag1);
  1657. }
  1658.  
  1659. void *MyAllocDosObjectTags(struct InstData *Inst,ULONG Type,ULONG Tag1,...)
  1660. {
  1661.         return AllocDosObject(Type,(struct TagItem *)&Tag1);
  1662. }
  1663. void MySystemTags(struct Library *DSBse,char *Cmd,ULONG Tag0,...)
  1664. {
  1665. #undef DOSBase
  1666. #define DOSBase DSBse
  1667.         SystemTagList(Cmd,(struct TagItem *)&Tag0);
  1668. #undef DOSBase
  1669. }
  1670.  
  1671. #define DOSBase DSBse
  1672. int __asm __saveds SubSubProc(register __a0 char *ArgString,register __d0 long Length)
  1673. {
  1674.         char StringBuf[1000];
  1675.         char *StringPtr;
  1676.         BPTR FH;
  1677.         struct Library *DSBse;
  1678.  
  1679.         DSBse=OpenLibrary("dos.library",36);
  1680.         if (!DSBse) return 0;
  1681.  
  1682.         FH=(BPTR)GetInt(ArgString,&StringPtr);
  1683.  
  1684. /*      if (IsInteractive(FH)) {
  1685.                 Write(FH,"Interactive\n",12);
  1686.         }*/
  1687.         strcpy(StringBuf,StringPtr);
  1688.     MySystemTags(DSBse,(StringBuf[0]) ? StringBuf : "execute S:remote-startup",
  1689.              SYS_Input,FH,
  1690.              SYS_Output,FH,
  1691.              NP_ConsoleTask,((struct FileHandle *)BADDR(FH))->fh_Type,
  1692.              NP_Cli,TRUE,
  1693.              TAG_END);
  1694.  
  1695.         Forbid();
  1696.         Close(FH);
  1697.         return 0;
  1698. }
  1699. #undef DOSBase
  1700.  
  1701.